package winOrDie.GameEngine.RT.mp;



import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.Vector;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;


import winOrDie.Game.WoD_Game;
import winOrDie.GameEngine.RT.Bucket;
import winOrDie.GameEngine.RT.WoD_Event;
import winOrDie.GameEngine.RT.WoD_Event_Processor;
import winOrDie.GameEngine.RT.plyrs.Hoggle;
import winOrDie.Net.WoD_Net_Protocol_Manager;
import winOrDie.Net.Client.WoD_Client_RT;
import winOrDie.Net.Client.WoD_Client_RT_Event;
import winOrDie.Net.Client.WoD_Client_RT_Listener;
import winOrDie.Net.Client.WoD_Peer;
import winOrDie.Net.Client.WoD_Peers_List;
import winOrDie.Net.RT.WoD_RT_Client_Movement;
import winOrDie.Net.RT.WoD_RT_Game_Info;
import winOrDie.Sound.Music.PlaySoundStream;

import winOrDie.Sound.Voice.WoD_Voice;
import winOrDie.Sound.Voice.WoD_Voice_Time;

//+:public -:private #:protected $:static F:final
public class MapBoard extends Canvas 
implements WoD_Event_Processor,
WoD_Client_RT_Listener
{

	/**
	 * miliseconds refresh interval
	 */
	public static final int FPS = 40;
	
	
	public static class PLAYER_ROL 
	{
		public static int Captain = 1;
		public static int Princess = 2;
		public static int Pirate = 3;
	}
	
	//tipografias
	private Font largeFont;
	private Font titleFont;
	//private Font smallFont;
	
	//campo
	/* campo_x -> pixels hasta el cuadro de mapa por la izquierda
	 * campo_xx -> pixels del cuadro de mapa de grosor
	 * campo_y -> pixels hasta el cuadro de mapa por arriba
	 * campo_yy -> pixels del cuadro del mapa de alto
	 * borde -> pixels del borde del mapa (el mapa queda dentro)
	 * cuadro -> tama�o de los cuadros de los pasillos del mapa
	 */
	private static int campo_x = 90;
	private static int campo_y = 80;
	private final static int cuadro = 20;
//	private int campo_xx = BOARDSIZE.x - campo_x*2;
	private int campo_xx = 41 * cuadro;

//	private int campo_yy = BOARDSIZE.y - campo_y/2 - campo_y; // y/2 - y porque el de arriba es el doble que el de abajo
	private int campo_yy = 29 * cuadro;
	private static int borde = 10; // ojo que hay un borde a cada lado

//	private String mapName = "jennytheflays.xml";
//	private String mapName = "base.xml";
//	private String mapName = "cruz.xml";
	private String mapName = "inferno.xml";

	//private String mapName = "jennytheflays.txt";
	//private String mapName = "base.txt";
	//private String mapName = "nada.txt";
	//private String mapName = "base_test.txt";
	private static Mapping mapLayer;
	// filas y columnas del mapa
	private final int columnasMap = (campo_xx - borde*2)/cuadro;
	private final int filasMap = (campo_yy - borde*2)/cuadro;

	//Hoggle-jugador
	private int rolPlayer;
	//Hoggle player = new Hoggle(campo_x + borde,campo_y + borde, cuadro, rolPlayer);
	
//	private int[] entradaPlayer = Mapping.entradaRandom();
	private int[] entradaPlayer;
	private Bucket bucket = null;
	private long timeOffset = 0L;
	
	private boolean partidaTerminada = false;
	
	private WoD_Net_Protocol_Manager woDNetProtocolManager = new WoD_Net_Protocol_Manager();

	
	
	private int nJugadores;
	private static int jugador;
	private static Hoggle player[];
	// Casilla actual al moverse de los vertices entrantes en una Casilla nueva
	private int xActual;
	private int yActual;
	private int xInicialPersonal;
	private int yInicialPersonal;
	
	private boolean hayTorre = false; //para ver si se pint� la torre en cada barrido
	// �ltima tecla pulsada de posicion, se inicializa a espacio o a cero segun teclado o flechas
	//private char memoMoveChar = ' ';
	//private int memoMoveInt = 0;
	
	//matriz del mapa
	//private char[][] mapLayer;
	
	private Image scenario;
	private Image labyrinth;
	//carga las imagenes para el escenario
	private static Imagenes imagenesEscenario = new Imagenes();
	
	public final static Point BOARDSIZE = new Point(1000, 700);

	public static int getCuadro() {
		return cuadro;
	}
	public void setTimeOffset(long timeOffset) {
		this.timeOffset = timeOffset;
	}
	
	
	/**
	 ******************************************************************************
	 * Listeners
	 *
	 ******************************************************************************
	 */
	private Vector<WoD_MapBoard_Listener> listeners = null;

	public synchronized void add_WoD_MapBoard_Listener(WoD_MapBoard_Listener listener)
	{
		listeners.add(listener);
	}
	
	public synchronized void remove_WoD_MapBoard_Listener(WoD_MapBoard_Listener listener)
	{
		listeners.remove(listener);
	}
	
	public void notify_WoD_MapBoard_Change(WoD_MapBoard_Event event)
	{
		for (WoD_MapBoard_Listener listener : listeners) {
			listener.on_WoD_MapBoard_Change(event);
		}
	}
	
	
	/**
	 * Voice
	 */
	public static WoD_Voice wod_Voice = null;
	public static WoD_Voice_Time woDVoiceTime = null;
	
	
	
	
	
	
	
	/**
	 * Initializes the map board
	 * @param player_Rol
	 * @param num_players
	 * @param ID
	 */
	private void initialize_Map_Board(WoD_Peers_List woDPeersList, int ID)
	{
		listeners = new Vector<WoD_MapBoard_Listener>();
		
		
		/**
		 * jugador
		 */
		jugador = ID;

		try {
			initialize_Players(woDPeersList);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		

		
//		player[1] = new Hoggle(verticeXcasilla(entradaPlayer[0]),verticeYcasilla(entradaPlayer[1]), cuadro, 3, 4);

		/**
		 * mapa
		 */
		try {
			mapLayer = new Mapping(columnasMap, filasMap, mapName, !visionHuggle());
//			mapLayer = new Mapping(columnasMap, filasMap, mapName, true);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		
		
		
		if (player[jugador].isHero()){
			mapLayer.recorrerZona(xInicialPersonal, yInicialPersonal, player[jugador].getVision());
			paintLabyrinth();
		}
		
		/**
		 * net
		 */
		bucket = new Bucket(this);
		
		// inicializar las tipografias
		getDisplay().loadFont("tipos\\dc_o.ttf");
		largeFont = new Font(getDisplay(), "Dark Crystal Outline", 40, SWT.NORMAL);
		titleFont = new Font(getDisplay(), "Dark Crystal Outline", 80, SWT.NORMAL);

		//smallFont = new Font(getDisplay(), "Arcade", 15, SWT.NORMAL);
		
		// colocar escenario de fondo
		paintScenario();
		
		addPaintListener(new PaintListener() {
			//@Override
			public void paintControl(PaintEvent e) {
				MapBoard.this.paintControl(e);
				

			}
		});

		addDisposeListener(new DisposeListener() {
			//@Override
			public void widgetDisposed(DisposeEvent e) {
				MapBoard.this.widgetDisposed(e);
			}
		});

		
		Runnable runnable = new Runnable() {
			
			@Override
			public void run() {
				/**
				 * Notify first position
				 */
				long event_Time = Long.valueOf(System.currentTimeMillis() + timeOffset).longValue();
				WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(jugador, player[jugador].getBound().x, player[jugador].getBound().y, event_Time);
				WoD_MapBoard_Event mapBoardEvent = new WoD_MapBoard_Event(this);
				mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.MOVE);
				mapBoardEvent.setData(clientMovement);
				notify_WoD_MapBoard_Change(mapBoardEvent);
				notify_WoD_MapBoard_Change(mapBoardEvent);	
			}
		};
		
		getDisplay().timerExec(1000, runnable);
		
		
	}
	
	
	/**
	 * Initializes the map board
	 * @param player_Rol
	 * @param num_players
	 * @param ID
	 */
	private void initialize_Map_Board_Old(int player_Rol, int num_players, int ID)
	{
		listeners = new Vector<WoD_MapBoard_Listener>();
		
		
		/**
		 * jugador
		 */
		rolPlayer = player_Rol; //rol del jugador  1 -> Hoggle  2 -> Doncella  3 -> Pirata
		entradaPlayer = Mapping.entradaRandom(rolPlayer);
		nJugadores = num_players;
		player = new Hoggle[nJugadores];
		jugador = ID;
		player[jugador] = new Hoggle(verticeXcasilla(entradaPlayer[0]),verticeYcasilla(entradaPlayer[1]), cuadro, rolPlayer, 4);
		
		
//		player[1] = new Hoggle(verticeXcasilla(entradaPlayer[0]),verticeYcasilla(entradaPlayer[1]), cuadro, 3, 4);

		/**
		 * mapa
		 */
		try {
			
			mapLayer = new Mapping(columnasMap, filasMap, mapName, !visionHuggle());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		
		
		
		if (player[jugador].isHero()){
			mapLayer.recorrerZona(entradaPlayer[0], entradaPlayer[1], player[jugador].getVision());
			paintLabyrinth();
		}
		
		/**
		 * net
		 */
		bucket = new Bucket(this);
		
		// inicializar las tipografias
		getDisplay().loadFont("tipos\\dc_o.ttf");
		largeFont = new Font(getDisplay(), "Dark Crystal Outline", 40, SWT.NORMAL);
		titleFont = new Font(getDisplay(), "Dark Crystal Outline", 80, SWT.NORMAL);

		//smallFont = new Font(getDisplay(), "Arcade", 15, SWT.NORMAL);
		
		// colocar escenario de fondo
		paintScenario();
		
		addPaintListener(new PaintListener() {
			//@Override
			public void paintControl(PaintEvent e) {
				MapBoard.this.paintControl(e);

			}
		});

		addDisposeListener(new DisposeListener() {
			//@Override
			public void widgetDisposed(DisposeEvent e) {
				MapBoard.this.widgetDisposed(e);
			}
		});

		
		
		
	}
	
	private KeyListener get_keyListener_WoD_Map_Board()
	{
		
		KeyListener keyListener = new KeyListener() {
			
		
		
		private long last_TouchTime = 0L;
		private long touch_Step = MapBoard.FPS * 5;
		
		public void keyPressed(KeyEvent e) {
			//System.out.println(e.character);
			
			//driver para evitar que se desplace muy rapido
			long currentTime = System.currentTimeMillis();
			if (currentTime < last_TouchTime + touch_Step) return;
			else last_TouchTime = currentTime;
			
			
			WoD_Event event = null;
			int[] bloqueMov = new int[5];
			
			switch (e.character | e.keyCode) {
			case 'w':
			case 'W':
			case SWT.ARROW_UP:
				//sube
				
				if (partidaTerminada) break;
		
				//donde estoy? previsi�n de movimiento, si donde se desplazaria no puede, no se desplaza
				//1� estoy dentro del mapa si me desplazo?
				if ((dentroMapa(player[jugador].getBound().x ,player[jugador].getBound().y - player[jugador].getSpeed())) 
						&& (dentroMapa(player[jugador].getBound().x + player[jugador].getWidth() ,player[jugador].getBound().y - player[jugador].getSpeed()))){
					
					/* 2� chocar�? cambio de Casilla?
					 * hay un pasillo en la parte superior? (est� subiendo)
					 * si cambia de Casilla en un vertice superior, se mira si la siguiente es pasillo, si lo es todo bien
					 */
					
					//if ((cambioCasilla(player.getBound().x, player.getBound().y, 'U'))) System.out.println("cambio");
					// si cambio de Casilla, mira si es pasillo, solo que uno no lo sea ya no se mueve
					//1er vertice
					if ((cambioCasilla(player[jugador].getBound().x, player[jugador].getBound().y, 'U')))
						if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x, campo_x, 0))
								, (futuraCasilla(player[jugador].getBound().y, campo_y, -1)))) break;
					//2� vertice
					if ((cambioCasilla(player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y, 'U')))
							if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x + player[jugador].getWidth(), campo_x, 0))
									, (futuraCasilla(player[jugador].getBound().y, campo_y, -1)))) break;

					
					/**
					 * guarda los datos con la posicion nueva y crea el evento
					 */
					bloqueMov = player[jugador].moveUP();
					event = new WoD_Event(jugador, WoD_Event.MOVE);
					event.setPlayer(jugador);
					long event_Time = Long.valueOf(System.currentTimeMillis() + timeOffset).longValue();
					event.setTs(event_Time);
//					event.setCoordX(player[jugador].getBound().x);
//					event.setCoordY(player[jugador].getBound().y);
//					event.setCoordX_old(player[jugador].getBound_doncella().x);
//					event.setCoordY_old(player[jugador].getBound_doncella().y);
					event.setMirando(player[jugador].getMirando());
					event.setEstadoPartida(mapLayer.getEstadoPartida());
					event.setCoordX(bloqueMov[0]);
					event.setCoordY(bloqueMov[1]);
					event.setCoordX_old(bloqueMov[2]);
					event.setCoordY_old(bloqueMov[3]);
					event.setMirando(bloqueMov[4]);
					
//					System.out.println(event.getTs());
					
					bucket.addEvent(event);
					
					
					/**
					 * Notify Move event
					 */
					
					System.out.println("Event TS: " + event.getTs() + " offset: " + timeOffset);
					
					//WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(jugador, bloqueMov[0], bloqueMov[1], System.currentTimeMillis() + timeOffset);
					WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(event.getPlayer(), event.getCoordX(), event.getCoordY(), event.getTs());
					WoD_MapBoard_Event mapBoardEvent = new WoD_MapBoard_Event(this);
					mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.MOVE);
					mapBoardEvent.setData(clientMovement);
					notify_WoD_MapBoard_Change(mapBoardEvent);
					
					
//					sacandoDeLaCaseta(jugador);
					
					
					// si antes pulsaste otra tecla, hay que mirar el mapa nuevo despejado si eres Hoggle
					//if ((player.isHero())&&((e.character != memoMoveChar)||(e.keyCode != memoMoveInt)))
					
//						paintHuggleEyes(player[jugador].getBound().x, player[jugador].getBound().y
//								, player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y
//								, player[jugador].getVision());
					//	;
						
//					System.out.println(e.character + " " + e.keyCode + "ARRIBA");
					
					// se guarda el nuevo valor pulsado
					//memoMoveChar = e.character;
					//memoMoveInt = e.keyCode;
				}
			
				break;

			case 's':
			case 'S':
			case SWT.ARROW_DOWN:
				//baja
				
				if (partidaTerminada) break;

				if ((dentroMapa(player[jugador].getBound().x ,player[jugador].getBound().y + player[jugador].getHeight() + player[jugador].getSpeed())) 
						&& (dentroMapa(player[jugador].getBound().x + player[jugador].getWidth() ,player[jugador].getBound().y + player[jugador].getHeight() + player[jugador].getSpeed()))){

					// si cambio de Casilla, mira si es pasillo, solo que uno no lo sea ya no se mueve
					//1er vertice
					if ((cambioCasilla(player[jugador].getBound().x, player[jugador].getBound().y + player[jugador].getHeight(), 'D')))
						if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x, campo_x, 0))
								, (futuraCasilla(player[jugador].getBound().y + player[jugador].getHeight(), campo_y, 1)))) break;
					//2� vertice
					if ((cambioCasilla(player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y + player[jugador].getHeight(), 'D')))
							if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x + player[jugador].getWidth(), campo_x, 0))
									, (futuraCasilla(player[jugador].getBound().y + player[jugador].getHeight(), campo_y, 1)))) break;

					
					/**
					 * guarda los datos con la posicion nueva y crea el evento
					 */
					bloqueMov = player[jugador].moveDOWN();
					event = new WoD_Event(jugador, WoD_Event.MOVE);
					event.setPlayer(jugador);
					long event_Time = Long.valueOf(System.currentTimeMillis() + timeOffset).longValue();
					event.setTs(event_Time);
					event.setEstadoPartida(mapLayer.getEstadoPartida());
					event.setCoordX(bloqueMov[0]);
					event.setCoordY(bloqueMov[1]);
					event.setCoordX_old(bloqueMov[2]);
					event.setCoordY_old(bloqueMov[3]);
					event.setMirando(bloqueMov[4]);
					
					bucket.addEvent(event);
					
					/**
					 * Notify Move event
					 */
					System.out.println("Event TS: " + event.getTs() + " offset: " + timeOffset);
					
					//WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(jugador, bloqueMov[0], bloqueMov[1], System.currentTimeMillis() + timeOffset);
					WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(event.getPlayer(), event.getCoordX(), event.getCoordY(), event.getTs());
					WoD_MapBoard_Event mapBoardEvent = new WoD_MapBoard_Event(this);
					mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.MOVE);
					mapBoardEvent.setData(clientMovement);
					notify_WoD_MapBoard_Change(mapBoardEvent);
//					sacandoDeLaCaseta(jugador);
					
					
					// si antes pulsaste otra tecla, hay que mirar el mapa nuevo despejado si eres Hoggle
					//if ((player.isHero())&&((e.character != memoMoveChar)||(e.keyCode != memoMoveInt)))
//						paintHuggleEyes(player[jugador].getBound().x, player[jugador].getBound().y + player[jugador].getHeight()
//								, player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y + player[jugador].getHeight()
//								, player[jugador].getVision());
					//	;
					
						
						
						
					// se guarda el nuevo valor pulsado
					//memoMoveChar = e.character;
					//memoMoveInt = e.keyCode;
					
				}
				
				break;

			case 'a':
			case 'A':
			case SWT.ARROW_LEFT:
				//izquierda
				
				if (partidaTerminada) break;
				
				if ((dentroMapa(player[jugador].getBound().x - player[jugador].getSpeed(),player[jugador].getBound().y)) 
						&& (dentroMapa(player[jugador].getBound().x - player[jugador].getSpeed(),player[jugador].getBound().y + player[jugador].getHeight()))){
					
					// si cambio de Casilla, mira si es pasillo, solo que uno no lo sea ya no se mueve
					//1er vertice
					if ((cambioCasilla(player[jugador].getBound().x, player[jugador].getBound().y, 'L')))
						if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x, campo_x, -1))
								, (futuraCasilla(player[jugador].getBound().y, campo_y, 0)))) break;
					//2� vertice
					if ((cambioCasilla(player[jugador].getBound().x, player[jugador].getBound().y + player[jugador].getHeight(), 'L')))
						if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x, campo_x, -1))
								, (futuraCasilla(player[jugador].getBound().y + player[jugador].getHeight(), campo_y, 0)))) break;						
					
					
					/**
					 * guarda los datos con la posicion nueva y crea el evento
					 */
					bloqueMov = player[jugador].moveLEFT();
					event = new WoD_Event(jugador, WoD_Event.MOVE);
					event.setPlayer(jugador);
					long event_Time = Long.valueOf(System.currentTimeMillis() + timeOffset).longValue();
					event.setTs(event_Time);
					event.setEstadoPartida(mapLayer.getEstadoPartida());
					event.setCoordX(bloqueMov[0]);
					event.setCoordY(bloqueMov[1]);
					event.setCoordX_old(bloqueMov[2]);
					event.setCoordY_old(bloqueMov[3]);
					event.setMirando(bloqueMov[4]);
					
					bucket.addEvent(event);
					
					/**
					 * Notify Move event
					 */
					System.out.println("Event TS: " + event.getTs() + " offset: " + timeOffset);
					
					//WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(jugador, bloqueMov[0], bloqueMov[1], System.currentTimeMillis() + timeOffset);
					WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(event.getPlayer(), event.getCoordX(), event.getCoordY(), event.getTs());
					WoD_MapBoard_Event mapBoardEvent = new WoD_MapBoard_Event(this);
					mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.MOVE);
					mapBoardEvent.setData(clientMovement);
					notify_WoD_MapBoard_Change(mapBoardEvent);
					
//					sacandoDeLaCaseta(jugador);

					
					// si antes pulsaste otra tecla, hay que mirar el mapa nuevo despejado si eres Hoggle
					//if ((player.isHero())&&((e.character != memoMoveChar)||(e.keyCode != memoMoveInt)))
//						paintHuggleEyes(player[jugador].getBound().x, player[jugador].getBound().y
//								, player[jugador].getBound().x, player[jugador].getBound().y + player[jugador].getHeight()
//								, player[jugador].getVision());
					//	;
					
						
					// se guarda el nuevo valor pulsado
					//memoMoveChar = e.character;
					//memoMoveInt = e.keyCode;
				}
			
				break;

			case 'd':
			case 'D':
			case SWT.ARROW_RIGHT:
				//derecha
				
				if (partidaTerminada) break;
				
				if ((dentroMapa(player[jugador].getBound().x + player[jugador].getWidth() + player[jugador].getSpeed() ,player[jugador].getBound().y)) 
						&& (dentroMapa(player[jugador].getBound().x + player[jugador].getWidth() + player[jugador].getSpeed() ,player[jugador].getBound().y + player[jugador].getHeight()))){
					
					// si cambio de Casilla, mira si es pasillo, solo que uno no lo sea ya no se mueve
					//1er vertice
					if ((cambioCasilla(player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y, 'R')))
						if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x + player[jugador].getWidth(), campo_x, 1))
								, (futuraCasilla(player[jugador].getBound().y, campo_y, 0)))) break;
					//2� vertice
					if ((cambioCasilla(player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y + player[jugador].getHeight(), 'R')))
						if (!mapLayer.pasillo((futuraCasilla(player[jugador].getBound().x + player[jugador].getWidth(), campo_x, 1))
								, (futuraCasilla(player[jugador].getBound().y + player[jugador].getHeight(), campo_y, 0)))) break;
					
					
					/**
					 * guarda los datos con la posicion nueva y crea el evento
					 */
					bloqueMov = player[jugador].moveRIGTH();
					event = new WoD_Event(jugador, WoD_Event.MOVE);
					event.setPlayer(jugador);
					long event_Time = Long.valueOf(System.currentTimeMillis() + timeOffset).longValue();
					event.setTs(event_Time);
					event.setEstadoPartida(mapLayer.getEstadoPartida());
					event.setCoordX(bloqueMov[0]);
					event.setCoordY(bloqueMov[1]);
					event.setCoordX_old(bloqueMov[2]);
					event.setCoordY_old(bloqueMov[3]);
					event.setMirando(bloqueMov[4]);
					
					// se a�aden al bucket local los datos con tu propio movimiento
					bucket.addEvent(event);
					
					/*
					 * se crea una cadena byte con los datos basicos para enviar al servidor
					 * id de nuestro jugador en el vector de jugadores, coordenada x, coordenada y,
					 * timestamp del movimiento
					 */
					
					/**
					 * Notify Move event
					 */
					System.out.println("Event TS: " + event.getTs() + " offset: " + timeOffset);
					
					//WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(jugador, bloqueMov[0], bloqueMov[1], System.currentTimeMillis() + timeOffset);
					WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement(event.getPlayer(), event.getCoordX(), event.getCoordY(), event.getTs());
					WoD_MapBoard_Event mapBoardEvent = new WoD_MapBoard_Event(this);
					mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.MOVE);
					mapBoardEvent.setData(clientMovement);
					notify_WoD_MapBoard_Change(mapBoardEvent);
					
					
//					sacandoDeLaCaseta(jugador);

					
					// si antes pulsaste otra tecla, hay que mirar el mapa nuevo despejado si eres Hoggle
					//if ((player.isHero())&&((e.character != memoMoveChar)||(e.keyCode != memoMoveInt)))
//						paintHuggleEyes(player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y
//								, player[jugador].getBound().x + player[jugador].getWidth(), player[jugador].getBound().y + player[jugador].getHeight()
//								, player[jugador].getVision());
					//	;
					
						
					// se guarda el nuevo valor pulsado
					//memoMoveChar = e.character;
					//memoMoveInt = e.keyCode;
				}
				
				break;

			case 't':
//				if ((!WoD_Voice.berrando()) && (WoD_Voice_Time.ceroOmenos())) WoD_Voice.berra();
//				else WoD_Voice.noBerres();
				if ((!WoD_Voice.berrando())) WoD_Voice.berra();
				else WoD_Voice.noBerres();
				break;
				
			case ' ':
				break;
			}

		}
		public void keyReleased(KeyEvent e) {
			// TODO Auto-generated method stub

		}
		};
		
		
		return keyListener;
	}
	
	
	/**
	 * Translates {@link WoD_Peer} Rol to {@link MapBoard} rol
	 * @param woDPeer
	 * @return int
	 */
	private int get_Rol(WoD_Peer woDPeer)
	{
		/**
		 * Set player Rol
		 */
		int player_Rol = PLAYER_ROL.Pirate;
		
		switch (woDPeer.getTeam()) {
		case WoD_Game.Game_Teams.Captain_Team:
			
			if (woDPeer.getROL() == WoD_Game.Game_Rols.Captain)
			{
				player_Rol = PLAYER_ROL.Captain;
			}
			else if (woDPeer.getROL() == WoD_Game.Game_Rols.Princess)
			{
				player_Rol = PLAYER_ROL.Princess;
			}
			
			break;

		default:
			break;
		}
		
		return player_Rol;
	}
	
	
	/**
	 * This private method initialize players
	 * @param woDPeersList
	 * @throws Exception
	 */
	private void initialize_Players(WoD_Peers_List woDPeersList) throws Exception
	{
		nJugadores = woDPeersList.getWoD_Peers().size();
		player = new Hoggle[nJugadores];
		
		for (int ID = 0; ID < woDPeersList.getWoD_Peers().size(); ID++) 
		{
			int position = woDPeersList.get_positionOfWoD_Peer_By_ID(ID);
			
			rolPlayer = get_Rol(woDPeersList.getWoD_Peers().get(position));
			entradaPlayer = Mapping.entradaRandom(rolPlayer);
			
			if (ID == jugador){
				xInicialPersonal = entradaPlayer[0];
				yInicialPersonal = entradaPlayer[1];
			}
			
			player[ID] =  new Hoggle(verticeXcasilla(entradaPlayer[0]),verticeYcasilla(entradaPlayer[1]), cuadro, rolPlayer, 4);
		}
		
	}
	
	
	public MapBoard(Composite 
			parent, 
			int style,
			WoD_Peer woDPeer,
			WoD_Client_RT woDClientRT,
			WoD_Peers_List woDPeersList,
			Long TS_Start,
			long offset,
			String mapName
			) 
	{
		super(parent, SWT.NO_BACKGROUND);// AL poner No_Brackground, la shell no
		// tiene fondo y hace una especie de
		// captura/transparencia
		
		timeOffset = offset;
		this.mapName = mapName; 
		
		
		/**
		 * Add this MapBoard as listener
		 */
		//woDClientRT.add_WoD_Client_RT_Listener(this);
		
		/**
		 * Start voice
		 */
		start_Voice(woDPeer, woDPeersList);

		
		
		/**
		 * Initialize map board
		 */
		//initialize_Map_Board(player_Rol, woDPeersList.getWoD_Peers().size(), woDPeer.getCliend_Id());
		initialize_Map_Board(woDPeersList, woDPeer.getCliend_Id());
		
		
		
		/**
		 * Wait to start
		 */
		long TS_wait = TS_Start - System.currentTimeMillis() - timeOffset;
		if (TS_wait > 0)
		{
			try {
				Thread.currentThread();
				Thread.sleep(TS_wait);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return;
			}
		}
		
		/**
		 * KeyListener
		 */
		addKeyListener(get_keyListener_WoD_Map_Board());
	}
	
	
	
	
	
	
	/**
	 * @return
	 * true si la posicion queda dentro del espacio del mapa	 
	 */
	private boolean dentroMapa(int x, int y){
		if (((x - campo_x - borde) >= 0) && (x <= campo_x + campo_xx - borde)
				&& ((y - campo_y - borde) >= 0) && (y <= campo_y + campo_yy - borde))
			return true;
		
		return false;
	}
	
	/**
	 * Con la posicion y la direccion indica si cambia de Casilla o no en el punto introducido
	 * @param x -> x actual
	 * @param y -> y actual
	 * @param letra -> direccion
	 * direcciones => U -> arriba / D -> abajo / L -> izquierda / R -> derecha
	 * @return -> cierto si cambia de Casilla
	 */
	private boolean cambioCasilla(int x, int y, char letra){
		// Casilla actual de un vertice
		xActual = futuraCasilla(x, campo_x, 0);
		yActual = futuraCasilla(y, campo_y, 0);
		//System.out.println(xActual +"XY"+ yActual);
		// Casilla futura
		//if (letra == 'U') return (yActual != (int)(y - campo_y - borde - player.getSpeed()) / cuadro);
		if (letra == 'U') return (yActual != futuraCasilla(y, campo_y, -1));
		else if (letra == 'D') return (yActual != futuraCasilla(y, campo_y, 1));
		else if (letra == 'L') return (xActual != futuraCasilla(x, campo_x, -1));
		else if (letra == 'R') return (xActual != futuraCasilla(x, campo_x, 1));

		return false;
	}
	
	
	public static Point get_Casilla(int pixel_X, int pixel_Y)
	{
		Point point = new Point(0, 0);
		point.x = futuraCasilla(pixel_X, campo_x, 0);
		point.y = futuraCasilla(pixel_Y, campo_y, 0);
		return point;
	}
	
	/**
	 * devuelve la Casilla futura segun la posicion y el movimiento
	 * @param i -> x o y actual
	 * @param campo_i
	 * @param mov -> -1 si el movimiento es descendente, 1 si es ascendente (si resta o suma posici�n respecto el vertice 0,0)
	 * 		si x = 0, devuelve la actual
	 * @return
	 */
	private static int futuraCasilla(int i, int campo_i, int mov){
		return ((i - campo_i - borde + mov * player[jugador].getSpeed()) / cuadro);
	}
	
	/**
	 * Devuelve si tiene la vision de Huggle o no, usea, si est� limitado a lo que explore
	 * @return true si est� limitado
	 */
	private boolean visionHuggle(){
		return player[jugador].isHero();
	}
	
	//@Override
	public Point computeSize(int wHint, int hHint, boolean changed) {

		return BOARDSIZE;
	}

	/**
	 * Pinta la pantalla completa
	 * @param e
	 */
	@SuppressWarnings("static-access")
	private void paintControl(PaintEvent e) {
		//doble buffer, se pinta todo sobre el y luego se muestra
		Image image_doblebuffer = new Image(getDisplay(), BOARDSIZE.x, BOARDSIZE.y);
		GC gc = new GC(image_doblebuffer);
		
		//fondo estatico
		gc.drawImage(scenario, 0, 0);

		//mapa estatico en estado actual
		gc.drawImage(labyrinth, verticeXcasilla(0), verticeYcasilla(0));
		
		//Pintamos a Hoggle
//		gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_RED));
//		gc.setAlpha(200);
//		gc.setAntialias(SWT.ON);
		
		/**
		 * pintamos a los jugadores segun su rol y estado de la partida
		 */
		for (int i = 0; i < nJugadores; i++) {
			//capitan sin doncella
			if (player[i].isHero() && !player[i].getDoncellaRescatada()){
				// ojo que la casilla este visible
				if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound().x, campo_x, 0)][futuraCasilla(player[i].getBound().y, campo_y, 0)].leerVisionCasilla() > 0)
					if (player[i].mira_derecha() != 0) gc.drawImage(imagenesEscenario.getHeroe_movR(player[i].mira_derecha()), player[i].getBound().x, player[i].getBound().y);
					else if (player[i].mira_izquierda() != 0) gc.drawImage(imagenesEscenario.getHeroe_movL(player[i].mira_izquierda()), player[i].getBound().x, player[i].getBound().y);
					else if (player[i].mira_arriba()) gc.drawImage(imagenesEscenario.getHeroe_movU(), player[i].getBound().x, player[i].getBound().y);
					else if (player[i].mira_abajo()) gc.drawImage(imagenesEscenario.getHeroe_movD(), player[i].getBound().x, player[i].getBound().y);
			//piratas
			}else if (player[i].isPirate()){
				// ojo que la casilla este visible
				if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound().x, campo_x, 0)][futuraCasilla(player[i].getBound().y, campo_y, 0)].leerVisionCasilla() > 0)
					if (player[i].mira_derecha() != 0) gc.drawImage(imagenesEscenario.getPirata_movR(player[i].mira_derecha()), player[i].getBound().x, player[i].getBound().y);
					else if (player[i].mira_izquierda() != 0) gc.drawImage(imagenesEscenario.getPirata_movL(player[i].mira_izquierda()), player[i].getBound().x, player[i].getBound().y);
					else if (player[i].mira_arriba()) gc.drawImage(imagenesEscenario.getPirata_movU(), player[i].getBound().x, player[i].getBound().y);
					else if (player[i].mira_abajo()) gc.drawImage(imagenesEscenario.getPirata_movD(), player[i].getBound().x, player[i].getBound().y);
			//capitan con doncella
			}else if (player[i].isHero() && player[i].getDoncellaRescatada()){ //heroe y doncella
				if (player[i].mira_derecha() != 0){
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound_doncella().x, campo_x, 0)][futuraCasilla(player[i].getBound_doncella().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getDoncella_movR(player[i].mira_derecha())
								, player[i].getBound_doncella().x, player[i].getBound_doncella().y);
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound().x, campo_x, 0)][futuraCasilla(player[i].getBound().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getHeroe_movR(player[i].mira_derecha())
								, player[i].getBound().x, player[i].getBound().y);
				}
				else if (player[i].mira_izquierda() != 0){
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound_doncella().x, campo_x, 0)][futuraCasilla(player[i].getBound_doncella().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getDoncella_movL(player[i].mira_izquierda())
								, player[i].getBound_doncella().x, player[i].getBound_doncella().y);
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound().x, campo_x, 0)][futuraCasilla(player[i].getBound().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getHeroe_movL(player[i].mira_izquierda())
								, player[i].getBound().x, player[i].getBound().y);
				}
				else if (player[i].mira_arriba()){
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound_doncella().x, campo_x, 0)][futuraCasilla(player[i].getBound_doncella().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getDoncella_movU()
								, player[i].getBound_doncella().x, player[i].getBound_doncella().y);
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound().x, campo_x, 0)][futuraCasilla(player[i].getBound().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getHeroe_movU()
								, player[i].getBound().x, player[i].getBound().y);
				}
				else if (player[i].mira_abajo()){
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound_doncella().x, campo_x, 0)][futuraCasilla(player[i].getBound_doncella().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getDoncella_movD()
								, player[i].getBound_doncella().x, player[i].getBound_doncella().y);
					// ojo que la casilla este visible
					if (mapLayer.getMapLayer()[futuraCasilla(player[i].getBound().x, campo_x, 0)][futuraCasilla(player[i].getBound().y, campo_y, 0)].leerVisionCasilla() > 0)
						gc.drawImage(imagenesEscenario.getHeroe_movD()
								, player[i].getBound().x, player[i].getBound().y);
				}
			}
			
			
			
			//		gc.fillOval(player.getBound().x, player.getBound().y, player.getWidth(),player.getHeight());
		}	
		
		e.gc.drawImage(image_doblebuffer, 0, 0);

		image_doblebuffer.dispose();
	}

	private void widgetDisposed(DisposeEvent e) {
		largeFont.dispose();
		titleFont.dispose();
		//smallFont.dispose();
		scenario.dispose();
	}

	/**
	 *  pinta el escenario fijo en "scenario" 
	 */
	private void paintScenario(){
		
		if (mapLayer.getEstadoPartida() != 0) scenario.dispose();
		
		scenario = new Image(getDisplay(), new Rectangle(0, 0, BOARDSIZE.x, BOARDSIZE.y));
		GC gc = new GC(scenario);
		gc.setAntialias(SWT.ON);
		
		//fondo negro
		gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
		gc.fillRectangle(0, 0, BOARDSIZE.x, BOARDSIZE.y);
		
		//campo
		if (mapLayer.getEstadoPartida() == 0) gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_MAGENTA));
		else if (mapLayer.getEstadoPartida() == 1) gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_RED));
		else if (mapLayer.getEstadoPartida() == 2) gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_YELLOW));
		else if (mapLayer.getEstadoPartida() == 3) gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE));

		gc.fillRectangle(campo_x, campo_y, campo_xx, campo_yy);
		gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
		gc.fillRectangle(campo_x + borde, campo_y + borde, campo_xx - borde*2, campo_yy - borde*2);
		
		//caminos
		//System.out.println("mapping1");
		//Mapping mp = new Mapping();
		//matriz del mapa, guarda el tipo de Casilla en la matriz
		//mapLayer = new char[40][28];
		
		//mapLayer = new Mapping((campo_xx - borde*2)/cuadro,(campo_yy - borde*2)/cuadro);
		//String charMap = mapLayer.openMap(mapName);
		//System.out.println("..." + charMap);
		//System.out.println("mapa cargado");
		
		/* !visionHuggle() esto se envia porque hace falta saber si el mapa estar� o no explorado de un principio
		 * entonces, si el rol es de Huggle (rol 1), no lo estar�, asi q enviar� falso en caso de ser Huggle y cierto para los dem�s		
		 */
		
		// ya tenemos la matriz con cada tipo de casilla, ahora vamos a pintarlo donde toca en el laberinto para luego
		paintLabyrinth();
				
		//titulo
		gc.setFont(largeFont);
		gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
		gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_RED));
		gc.drawText(mapName.substring(0, mapName.length()-4), campo_x, 30, true);

		System.out.println("SCENARIO PINTADO");
		
		gc.dispose();
	}
	
	
	
	
	/**
	 * pinta el mapa con sus paredes y dem�s, lo que es el mapa 100%
	 * este queda en la variable labyrinth como Image
	 */
	private void paintLabyrinth(){
//		System.out.println("LABYRINTH PINTADO");
		
		if (mapLayer.getEstadoPartida() != 0) labyrinth.dispose();
		
		labyrinth = new Image(getDisplay(), new Rectangle(0, 0, mapLayer.getColumnas()*cuadro, mapLayer.getFilas()*cuadro));
		GC gc = new GC(labyrinth);
		
		//fondo negro
		gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
		gc.fillRectangle(0, 0, mapLayer.getColumnas()*cuadro, mapLayer.getFilas()*cuadro);
		
		
		for (int i = 0; i < mapLayer.getFilas(); i++) {
			//System.out.println(" ");
			//System.out.print("fila " + i + "columna ");
			for (int j = 0; j < mapLayer.getColumnas(); j++) {
				//System.out.print(" " + mapLayer.leerValor(j, i) + " ");
				
				// hay que comprobar que la casilla sea visible
				if (mapLayer.Vision(j, i) != 0){
					// 1 pared
					if (mapLayer.leerValor(j, i) == '1') gc.drawImage(imagenesEscenario.getBarril(), verticeXcasillaEnLaberinto(j), verticeYcasillaEnLaberinto(i));

					// 0 pasillo
					else if (mapLayer.leerValor(j, i) == '0') gc.drawImage(imagenesEscenario.getPasillo(), verticeXcasillaEnLaberinto(j), verticeYcasillaEnLaberinto(i));
		
					// T torre de la doncella
					else if (mapLayer.leerValor(j, i) == 'T'){
						if (!hayTorre){
							hayTorre = true;
//							gc.drawImage(imagenesEscenario.getTorre(), verticeXcasillaEnLaberinto(j), verticeYcasillaEnLaberinto(i));
							gc.drawImage(imagenesEscenario.getTorre(), verticeXcasillaEnLaberinto(16), verticeYcasillaEnLaberinto(11));
						}
					}
					
					// R zona de rescate de doncella
//					else if (mapLayer.leerValor(j, i) == 'R') gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_YELLOW));
					
					
						// P zona de inicio de partida para los piratas
					else if (mapLayer.leerValor(j, i) == 'P') gc.drawImage(imagenesEscenario.getSueloPirata(), verticeXcasillaEnLaberinto(j), verticeYcasillaEnLaberinto(i));
					
//					else{
						// I zona de inicio de partida para el bueno
					else if (mapLayer.leerValor(j, i) == 'I') gc.drawImage(imagenesEscenario.getEntrada(), verticeXcasillaEnLaberinto(j), verticeYcasillaEnLaberinto(i));
		
//						else gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
							
//						gc.fillRectangle(verticeXcasillaEnLaberinto(j), verticeYcasillaEnLaberinto(i), cuadro, cuadro);
//					}
				}
			}
			
		}
		
		hayTorre = false;

		gc.dispose();
	}
		
	
	/**
	 * Pinta lo que ve Huggle
	 * hay que tener en cuenta que los 2 vertices que hay que enviar son los que van delante en orden de la marcha
	 * usea, si vas hacia arriba, se envian los de arriba, si es hacia abajo, pues los de abajo... (el orden da igual)
	 * @param x1 -> x actual de un vertice
	 * @param y1 -> y actual del mismo vertice
	 * @param x2 -> x actual del otro vertice
	 * @param y2 -> y actual del mismo vertice
	 * @param distancia -> distancia de vision
	 * direcciones => U -> arriba / D -> abajo / L -> izquierda / R -> derecha	 
	 */
	private void paintHuggleEyes(int x1, int y1,int x2, int y2, int distancia){
		
		int cambios = 0;
		int xTemp;
		int yTemp;
		
		// Casilla actual de un vertice
		xActual = futuraCasilla(x1, campo_x, 0);
		yActual = futuraCasilla(y1, campo_y, 0);

		if (mapLayer.recorrerZona(xActual, yActual, distancia)) cambios++;
		

		/* 
		 * se guarda la casilla actual para compararla con la siguiente
		 * luego, en caso de que esten en la misma casilla, no se vuelve a procesar el recorrido
		 * seria absurdo... mismos datos... mismo recorrido...
		 */
		xTemp = xActual;
		yTemp = yActual;
		
		// Casilla actual del otro vertice
		xActual = futuraCasilla(x2, campo_x, 0);
		yActual = futuraCasilla(y2, campo_y, 0);
		
		if ((xTemp != xActual) || (yTemp != yActual)){
			if (mapLayer.recorrerZona(xActual, yActual, distancia)) cambios++;
		}
		
		if (cambios > 0) paintLabyrinth();
	}
	
	/**
	 * Indicando la fila de la Casilla se devuelve el valor y sobre el escenario
	 * @param fila
	 * @return
	 */
	public int verticeYcasilla(int columna){
		// campo_y + borde + fila * cuadro
		//System.out.println("columna " + columna);
		//System.out.println("verticeYcasilla = " + (int)(campo_y + borde + columna * cuadro));
		
		return (campo_y + borde + columna * cuadro);
	}
	
	/**
	 * Indicando la fila de la Casilla se devuelve el valor y sobre el laberinto
	 * @param fila
	 * @return
	 */
	public int verticeYcasillaEnLaberinto(int columna){
		// campo_y + borde + fila * cuadro
		//System.out.println("columna " + columna);
		//System.out.println("verticeYcasilla = " + (int)(campo_y + borde + columna * cuadro));
		
		return (columna * cuadro);
	}
	
	/**
	 * Indicando la columna de la Casilla se devuelve el valor x sobre el escenario
	 * @param columna
	 * @return
	 */
	public int verticeXcasilla(int fila){
		// campo_x + borde + columa * cuadro
		//System.out.println("fila " + fila);
		//System.out.println("verticeXcasilla = " + (int)(campo_x + borde + fila * cuadro));
		
		return (campo_x + borde + fila * cuadro);
	}
	
	/**
	 * Indicando la columna de la Casilla se devuelve el valor x sobre el laberinto
	 * @param columna
	 * @return
	 */
	public int verticeXcasillaEnLaberinto(int fila){
		// campo_x + borde + columa * cuadro
		//System.out.println("fila " + fila);
		//System.out.println("verticeXcasilla = " + (int)(campo_x + borde + fila * cuadro));
		
		return (fila * cuadro);
	}
	
	/**
	 * detecta si es el capitan y si entra en zona de rescate lo indica en su configuracion
	 * se llama despues de cada movimiento
	 */
	public void sacandoDeLaCaseta(int i){
		/**
		 * detecta si el capitan entra en zona de rescate y lo indica en su configuracion
		 */
		if ((player[i].isHero()) && (!player[i].getDoncellaRescatada()))
			if (mapLayer.esZonaRescate(futuraCasilla(player[i].getBound().x, campo_x, 0), futuraCasilla(player[i].getBound().y, campo_y, 0))){
				player[i].setDoncellaRescatada();
				mapLayer.setEstadoPartida(1);
				paintScenario();
	//			mapLayer.eplorarMapaEntero();
	//			paintLabyrinth();
				System.out.println("RESCATE");
			}
	}
	
	/**
	 * detecta si el capitan esta con la doncella en una casilla de salida
	 * si es asi, cambia el estado de la partida a partida ganada por el capitan
	 * @param i
	 * @return cierto si es el capitan y ha llegado a la salida con la doncella
	 */
	public boolean capitanRescataDoncella(int i){
		if ((player[i].isHero()) && (player[i].getDoncellaRescatada()) 
				&& (mapLayer.esZonaSalida(futuraCasilla(player[i].getBound().x, campo_x, 0), futuraCasilla(player[i].getBound().y, campo_y, 0)))){
			mapLayer.setEstadoPartida(2);
			
			System.out.println("-----------CAPITAN GANA");
			partidaTerminada = true;
			paintScenario();
			return true;
		}
		return false;
	}
	
	/**
	 * detecta si un pirata coincide con el heroe o la doncella cuando est� fuera
	 * si es asi, cambia el estado de la partida a partida ganada por los piratas
	 * @param id jugador
	 * @return cierto si los piratas han ganado
	 */
	public boolean pirataAtrapaCapitanODoncella(int id){
		
		if (player[id].isHero()){
			// si es el heroe
			for (int j = 0; j < nJugadores; j++) {
				// si coincide con un pirata
				if (player[j].isPirate()){
						// el capitan
						if ((futuraCasilla(player[id].getBound().x, campo_x, 0) == futuraCasilla(player[j].getBound().x, campo_x, 0))
								&& (futuraCasilla(player[id].getBound().y, campo_y, 0) == futuraCasilla(player[j].getBound().y, campo_y, 0))){
							mapLayer.setEstadoPartida(3);
					
							System.out.println("-----------PIRATAS GANAN");
							partidaTerminada = true;
							paintScenario();
							return true;
						}
						
						// la doncella si esta fuera de la caseta
						if ((player[id].getDoncellaRescatada())
								&& (futuraCasilla(player[id].getBound_doncella().x, campo_x, 0) == futuraCasilla(player[j].getBound().x, campo_x, 0))
								&& (futuraCasilla(player[id].getBound_doncella().y, campo_y, 0) == futuraCasilla(player[j].getBound().y, campo_y, 0))){
							mapLayer.setEstadoPartida(3);
					
							System.out.println("-----------PIRATAS GANAN");
							partidaTerminada = true;
							paintScenario();
							return true;
						}
						
				}

			}
		}else if (player[id].isPirate()){
			// si es un pirata
			for (int j = 0; j < nJugadores; j++) {
				// si coincide con el heroe
				if (player[j].isHero()){ 
						// el capitan
						if ((futuraCasilla(player[id].getBound().x, campo_x, 0) == futuraCasilla(player[j].getBound().x, campo_x, 0))
								&& (futuraCasilla(player[id].getBound().y, campo_y, 0) == futuraCasilla(player[j].getBound().y, campo_y, 0))){
							mapLayer.setEstadoPartida(3);
					
							System.out.println("-----------PIRATAS GANAN");
							partidaTerminada = true;
							paintScenario();
							return true;
						}
						
						// la doncella si esta fuera de la caseta
						if ((player[j].getDoncellaRescatada())
								&& (futuraCasilla(player[j].getBound_doncella().x, campo_x, 0) == futuraCasilla(player[id].getBound().x, campo_x, 0))
								&& (futuraCasilla(player[j].getBound_doncella().y, campo_y, 0) == futuraCasilla(player[id].getBound().y, campo_y, 0))){
							mapLayer.setEstadoPartida(3);
					
							System.out.println("-----------PIRATAS GANAN");
							partidaTerminada = true;
							paintScenario();
							return true;
						}
				}
			}
		}
		return false;
	}
	
	/**
	 * fuerza a pasar a estado de partida 1, cuando la doncella esta fuera de la caseta siguiendo al capitan
	 */
	public void forzarEstadoDoncellaFueraDeCaseta(){
		mapLayer.setEstadoPartida(1);
		paintScenario();
		partidaTerminada = false;
		
		int i = -1;
		do{
			i++;
			if (player[i].isHero()) player[i].setDoncellaRescatada();
		}while((!player[i].isHero()) && (i < nJugadores - 1));
		
		System.out.println("-----CAMBIO A ESTADO 1 FORZADO");
		
	}
	
	/**
	 * fuerza a pasar a estado de partida 2, cuando el capitan ha llevado a la doncella a la salida
	 */
	public void forzarEstadoDoncellaRescatada_capitanGana(){
		mapLayer.setEstadoPartida(2);
		paintScenario();
		partidaTerminada = true;
		
		System.out.println("-----CAMBIO A ESTADO 2 FORZADO");
	}
	
	/**
	 * fuerza a pasar a estado de partida 3, cuando el capitan o la doncella son capturados por un pirata
	 */
	public void forzarEstado_piratasGanan(){
		mapLayer.setEstadoPartida(3);
		paintScenario();
		partidaTerminada = true;
		
		System.out.println("-----CAMBIO A ESTADO 3 FORZADO");
	}
	
	/**
	 * fuerza a pasar a estado de partida 0, cuando el capitan aun no ha encontrado a la doncella
	 */
	public void forzarEstadoNormal(){
		mapLayer.setEstadoPartida(0);
		paintScenario();
		partidaTerminada = true;
		
		int i = -1;
		do{
			i++;
			if (player[i].isHero()) player[i].setDoncellaNoRescatada();
		}while((!player[i].isHero()) && (i < nJugadores - 1));
		
		System.out.println("-----CAMBIO A ESTADO 0 FORZADO");
	}
	
	public void render() {
		if (!isDisposed()) {
			
			/**
			 * Bucket process events
			 */
			bucket.processRoundEvent(Long.valueOf(System.currentTimeMillis() + timeOffset).longValue());
			
			if (!isDisposed())
			{
				redraw();	
			}
			
		}
	}

	@Override
	public void processEvent(WoD_Event event) {
//		System.out.println("procesa");
		// TODO Auto-generated method stub
		switch (event.getType()) {
			
			case WoD_Event.MOVE:
				/**
				 * hacia donde mira
				 */
//				int eventoX = futuraCasilla(event.getCoordX(), campo_x, 0);
//				int actualX = futuraCasilla(player[event.getPlayer()].getBound().x, campo_x, 0);
//				int eventoY = futuraCasilla(event.getCoordY(), campo_y, 0);
//				int actualY = futuraCasilla(player[event.getPlayer()].getBound().y, campo_y, 0);
				
				// si no cambia de columna es que se mueve verticalmente
				if (futuraCasilla(event.getCoordX(), campo_x, 0) == futuraCasilla(player[event.getPlayer()].getBound().x, campo_x, 0)){
					if (futuraCasilla(event.getCoordY(), campo_y, 0) > futuraCasilla(player[event.getPlayer()].getBound().y, campo_y, 0))
						player[event.getPlayer()].setMirando(0);
					else if (futuraCasilla(event.getCoordY(), campo_y, 0) < futuraCasilla(player[event.getPlayer()].getBound().y, campo_y, 0))
						player[event.getPlayer()].setMirando(2);

				// si no cambia de fila es que se mueve lateralmente
				}else if (futuraCasilla(event.getCoordY(), campo_y, 0) == futuraCasilla(player[event.getPlayer()].getBound().y, campo_y, 0)){
					if (futuraCasilla(event.getCoordX(), campo_x, 0) > futuraCasilla(player[event.getPlayer()].getBound().x, campo_x, 0)){
						if (player[event.getPlayer()].getMirando() == 3) player[event.getPlayer()].setMirando(33);
						else player[event.getPlayer()].setMirando(3);
					}
					else if (futuraCasilla(event.getCoordX(), campo_x, 0) < futuraCasilla(player[event.getPlayer()].getBound().x, campo_x, 0)){
						if (player[event.getPlayer()].getMirando() == 1) player[event.getPlayer()].setMirando(11);
						else player[event.getPlayer()].setMirando(1);
					}
				}
				
				// si te has desplazado, la princesa tambien
				if (((futuraCasilla(event.getCoordX(), campo_x, 0) != futuraCasilla(player[event.getPlayer()].getBound().x, campo_x, 0)))
						|| (futuraCasilla(event.getCoordY(), campo_y, 0) != futuraCasilla(player[event.getPlayer()].getBound().y, campo_y, 0))){
					player[event.getPlayer()].setBounds_oldX(player[event.getPlayer()].getBound().x);
					player[event.getPlayer()].setBounds_oldY(player[event.getPlayer()].getBound().y);
				}

				player[event.getPlayer()].setBoundsX(event.getCoordX());
				player[event.getPlayer()].setBoundsY(event.getCoordY());
//				player[event.getPlayer()].setMirando(event.getMirando());
				
								
				if ((mapLayer.getEstadoPartida() == Mapping.RT_GAME_STATE.PRINCESS_OUT) &&
						(player[event.getPlayer()].isHero())
						)
				{
					player[event.getPlayer()].setDoncellaRescatada();
					paintScenario();
				}
				
				//sacandoDeLaCaseta(event.getPlayer());
				
				//if (!pirataAtrapaCapitanODoncella(event.getPlayer())) capitanRescataDoncella(event.getPlayer());
				
				
				/**
				 * Visión con Recursividad
				 */
				if ((event.getPlayer() == jugador) && (player[jugador].isHero())) paintHuggleEyes(event.getCoordX(), event.getCoordY()
						, event.getCoordX(), event.getCoordY()
						, player[jugador].getVision());
				
				/**
				 * mirando que el estado de la partida sea el que toca
				 */
				if (event.getEstadoPartida() != mapLayer.getEstadoPartida()){
					//if ((event.getEstadoPartida() == 1) && (mapLayer.getEstadoPartida() == 0)) forzarEstadoDoncellaFueraDeCaseta();
					if (event.getEstadoPartida() == 1) forzarEstadoDoncellaFueraDeCaseta();
					else if (event.getEstadoPartida() == 2) forzarEstadoDoncellaRescatada_capitanGana();
					else if (event.getEstadoPartida() == 3) forzarEstado_piratasGanan();
					else if (event.getEstadoPartida() == 0) forzarEstadoNormal();
					
					WoD_MapBoard_Event mapBoardEvent = null;
					switch (event.getEstadoPartida()) {
					case Mapping.RT_GAME_STATE.CAPTAIN_CAPTURED:
						mapBoardEvent = new WoD_MapBoard_Event(this);
						mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.CAPTAIN_CAPTURED);
						notify_WoD_MapBoard_Change(mapBoardEvent);
						break;
						
					case Mapping.RT_GAME_STATE.CAPTAIN_WINS:
						mapBoardEvent = new WoD_MapBoard_Event(this);
						mapBoardEvent.setEvent_Type(WoD_MapBoard_Event.Event_Types.CAPTAIN_WINS);
						notify_WoD_MapBoard_Change(mapBoardEvent);
						break;

					default:
						break;
					}
					
					
					
				}
				
				
//				System.out.println("Player: " + event.getPlayer() + " X: " + futuraCasilla(event.getCoordX(), campo_x, 0)
//									+ " Y: " + futuraCasilla(event.getCoordY(), campo_y, 0) + " X_D: " + futuraCasilla(event.getCoordX_old(), campo_x, 0)
//									+ " Y_D: " + futuraCasilla(event.getCoordY_old(), campo_y, 0) + " Mirando: " + event.getMirando()
//									+ " EstadoPartidaAnterior: " + event.getEstadoPartida() 
//									+ " EstadoPartidaActual: " + mapLayer.getEstadoPartida());
				
				break;
				
			default:
				break;
		}
	}

	
	
	
	
	
	@Override
	public void notify_Event_WoD_Client_RTChannel(WoD_Client_RT_Event event) {
	
		switch (event.getEvent_Type()) {
		case WoD_Client_RT_Event.GAME_ACTION:
			
			manage_Message_GAME_ACTION(event);
			
			break;

		default:
			break;
		}
		
	}
	
	
	private void manage_Message_GAME_ACTION(WoD_Client_RT_Event event)
	{
		DatagramPacket datagramPacket = (DatagramPacket) event.getData();
		
		try {
			WoD_RT_Game_Info woDRTGameInfo = woDNetProtocolManager.parse_GAME_RT_INFO(datagramPacket.getData());
			
//			if (woDRTGameInfo.get_Num_Players() != player.length)
//			{
//				Exception exception = new Exception("Player list corrupted");
//				throw exception;
//			}
			
			for (WoD_RT_Client_Movement movement : woDRTGameInfo.getClientMovements()) {
				WoD_Event woDEvent = get_WoD_Event_From_WoD_RT_Client_Movement(movement);
				woDEvent.setEstadoPartida(woDRTGameInfo.getGameState());
				
				bucket.addEvent(
						woDEvent
						);
			}
			
//			mapLayer.set_Estado_Partida(woDRTGameInfo.getGameState());
			
//			System.out.println("Estado " + woDRTGameInfo.getGameState());
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
	
	private WoD_Event get_WoD_Event_From_WoD_RT_Client_Movement(WoD_RT_Client_Movement movement)
	{
		WoD_Event event = new WoD_Event(movement.getID(), WoD_Event.MOVE);
		event.setPlayer(movement.getID());
		event.setTs(movement.getTimeStamp());
		
		event.setMirando(player[movement.getID()].getMirando());
		event.setEstadoPartida(mapLayer.getEstadoPartida());
		event.setCoordX(movement.getX());
		event.setCoordY(movement.getY());
		event.setCoordX_old(player[movement.getID()].getBound().x);
		event.setCoordY_old(player[movement.getID()].getBound().y);
		event.setMirando(player[movement.getID()].getMirando());
		
		return event;
	}
	

	/**
	 * This private method set and start voice module
	 */
	private void start_Voice(WoD_Peer woDPeer, WoD_Peers_List woDPeersList)
	{
		/**
		 * voice
		 */
		ArrayList<WoD_Peer> woDPeers_My_Team = new ArrayList<WoD_Peer>();
		for (WoD_Peer woDPeer_my_team : woDPeersList.getWoD_Peers()) {
			if (woDPeer_my_team.getTeam() == woDPeer.getTeam())
			{
				woDPeers_My_Team.add(woDPeer_my_team);
			}
		}
		
		wod_Voice = new WoD_Voice(woDPeers_My_Team);
		wod_Voice.setIn_port(woDPeer.getVoice_UDP_Port());
		
		wod_Voice.startTest(true);
		
		
	}
}
